﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using FlickrNet;

namespace FlickrListr
{
	public partial class MainForm : Form
	{
		private static readonly string apiKey_ = "f720046fa15bbbecac5333bc02e5f9ec";
		private static readonly string sharedSecret_ = "dc18871b7421c180";
		private string tempFrob_;
		private Flickr flickr_;
		private Auth auth_;
		private Dictionary<string, string> PhotosetIds_ = new Dictionary<string, string>();

		public DateTime FromDateTime { get {
			return fromDatePicker.Value.Date.Add(fromTimePicker.Value.TimeOfDay).ToUniversalTime(); } }

		public DateTime ToDateTime { get {
			return toDatePicker.Value.Date.Add(toTimePicker.Value.TimeOfDay).ToUniversalTime(); } }

		public MainForm()
		{
			InitializeComponent();
			dateRadioButton.Checked = true;
			UpdateControls_();
			flickr_ = new Flickr(apiKey_, sharedSecret_);
		}

		private void OnAuthenticateButtonClicked_(object sender, EventArgs e)
		{
			bool hasPreexistingFrob = !String.IsNullOrEmpty(tempFrob_);
			if (!hasPreexistingFrob) {
				tempFrob_ = flickr_.AuthGetFrob();
				string sAuthenticationUrl = flickr_.AuthCalcUrl(tempFrob_, AuthLevel.Write);
				// fixme: figure out how we can cache the auth token/frob.
				System.Diagnostics.Process.Start(sAuthenticationUrl);
				MessageBox.Show("I have completed the authentication process.  Please let me continue.");
			}
			
			try {
				auth_ = flickr_.AuthGetToken(tempFrob_);
				flickr_.AuthToken = auth_.Token;
			}
			catch (FlickrException)
			{
				MessageBox.Show("Authentication not yet achieved.  You will have to reauthenticate.");
				if (hasPreexistingFrob)
					tempFrob_ = null;
				return;
			}
			
			MessageBox.Show("Authentication complete.  Welcome, " + auth_.User.Username + ".");
			if (setRadioButton.Checked)
				if (!RetrieveSets_())
					dateRadioButton.Checked = true;
			UpdateControls_();
		}

		private void OnPerformButtonClicked_(object sender, EventArgs e)
		{
			outputTextBox.Text = "";
			progressBar.Value = 0;

			if (dateRadioButton.Checked)
				RetrievePhotosFromDateRange_();
			else
				RetrievePhotosFromSet_();
		}
		
		private void RetrievePhotosFromDateRange_()
		{
			PhotoSearchOptions photoSearchOptions = new PhotoSearchOptions(auth_.User.UserId);
			photoSearchOptions.MinUploadDate = FromDateTime;
			photoSearchOptions.MaxUploadDate = ToDateTime;
			photoSearchOptions.Extras = PhotoSearchExtras.DateTaken | PhotoSearchExtras.DateUploaded;
			Photos photos = flickr_.PhotosSearch(photoSearchOptions);

			photoCountLabel.Text = photos.TotalPhotos.ToString("N0");
			progressBar.Maximum = Convert.ToInt32(photos.TotalPhotos); // .TotalPhotos is a long

			while (photos.PageNumber <= photos.TotalPages) {
				OutputPhotoDetails_(photos.PhotoCollection);
				photoSearchOptions.Page = Convert.ToInt32(photos.PageNumber + 1);
				photos = flickr_.PhotosSearch(photoSearchOptions);
			}
		}

		private void RetrievePhotosFromSet_()
		{
			string photosetTitle = setsComboBox.Items[setsComboBox.SelectedIndex].ToString();
			if (!PhotosetIds_.ContainsKey(photosetTitle)) {
				MessageBox.Show("Please select a valid set.  Currently selected: " + photosetTitle);
				return;
			}

			Photoset photoset = flickr_.PhotosetsGetPhotos(PhotosetIds_[photosetTitle], 1, 1);

			int photoCount = photoset.NumberOfPhotos;
			photoCountLabel.Text = photoCount.ToString("N0");
			progressBar.Maximum = photoCount;

			int photosPerPage = 100;
			int totalPages = photoCount / photosPerPage + (photoCount % photosPerPage > 0 ? 1 : 0);

			for (int page = 1; page <= totalPages; ++page) {
				photoset = flickr_.PhotosetsGetPhotos(PhotosetIds_[photosetTitle], page, photosPerPage);
				OutputPhotoDetails_(photoset.PhotoCollection);
			}
		}
		
		private void OutputPhotoDetails_(Photo[] photos)
		{
			foreach (Photo photo in photos) {
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append(photo.Title);
				stringBuilder.Append(", ");
				stringBuilder.Append(photo.DateUploaded.ToLocalTime().ToString());
				stringBuilder.Append(", ");
				stringBuilder.Append(photo.DateTaken.ToLocalTime().ToString());
				stringBuilder.Append(Environment.NewLine);
				outputTextBox.AppendText(stringBuilder.ToString());
				progressBar.Value = progressBar.Value + 1;
			}
		}
		
		private void OnSetRadioClicked_(object sender, EventArgs eventArgs)
		{
			if (!RetrieveSets_())
				dateRadioButton.Checked = true;
			UpdateControls_();
		}

		private bool RetrieveSets_()
		{
			if (setsComboBox.Items.Count > 0 || auth_ == null)
				return true;
			if (MessageBox.Show("Would you like to load sets?  This process could take up to a minute.", "Load Sets?",
					MessageBoxButtons.YesNo) == DialogResult.No)
				return false;

			Photosets photosets = flickr_.PhotosetsGetList();
			foreach (Photoset photoset in photosets.PhotosetCollection) {
				PhotosetIds_[photoset.Title] = photoset.PhotosetId;
				setsComboBox.Items.Add(photoset.Title);
			}
			return true;
		}

		private void OnControlChanged_(object sender, EventArgs eventArgs)
			{ UpdateControls_(); }

		private void UpdateControls_()
		{
			setsComboBox.Enabled = setRadioButton.Checked;
			bool usingDates = dateRadioButton.Checked;
			fromLabel.Enabled = usingDates;
			fromDatePicker.Enabled = usingDates;
			fromAtLabel.Enabled = usingDates;
			fromTimePicker.Enabled = usingDates;
			toLabel.Enabled = usingDates;
			toDatePicker.Enabled = usingDates;
			toAtLabel.Enabled = usingDates;
			toTimePicker.Enabled = usingDates;

			authenticateButton.Enabled = auth_ == null;

			// Need at least 1 sec difference (> 500 ms due to rounding) if using dates
			performButton.Enabled = auth_ != null
				&& (dateRadioButton.Checked && ToDateTime - FromDateTime > TimeSpan.FromMilliseconds(500)
					|| setRadioButton.Checked && setsComboBox.SelectedIndex >= 0);
		}
	}
}
